<template>
  <div>
    <el-empty
      description="先选择测试项"
      v-if="!props.testName"
      style="height: 600px; width: 100%"
    />

    <div ref="chartRef" style="height: 600px; width: 100%" v-else></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
import axios from "axios";
import * as echarts from "echarts";
import type { ECharts, EChartsOption } from "echarts";
import { ElMessage } from "element-plus";

/** ===== Props =====
 * apiUrl: 数据接口
 * active: 所在的 tab 是否处于激活（显示）状态；激活时触发 resize
 * ucl/mean/lcl: 阈值线（可选，不传则不画）
 * jitter: 是否对同一 site 做轻微“抖动”，让竖条更“壮”
 */
const props = withDefaults(
  defineProps<{
    apiUrl?: string;
    active?: boolean;
    jitter?: boolean;
    testName?: string;
    dbPath?: string;
  }>(),
  {
    apiUrl: "https://localhost:44389/api/Stdf/GetSiteEcharts",
    active: false,
    jitter: false,
    dbPath: null
  }
);

const ucl = ref<number | null>(null);
const mean = ref<number | null>(null);
const lcl = ref<number | null>(null);

const chartRef = ref<HTMLDivElement | null>(null);
let chart: ECharts | null = null;
let loaded = false;

function initChart() {
  if (!chartRef.value) return;
  chart = echarts.init(chartRef.value);
}

function disposeChart() {
  chart?.dispose();
  chart = null;
}

function resize() {
  chart?.resize();
}

/** 构造可选的 markLine（更粗） */
function buildMarkLines() {
  const lines: any[] = [];
  if (ucl.value != null) lines.push({ yAxis: ucl.value, name: "上限值" });
  if (mean.value != null) lines.push({ yAxis: mean.value, name: "良品均值" });
  if (lcl.value != null) lines.push({ yAxis: lcl.value, name: "下限值" });
  return lines.length
    ? {
        symbol: "none",
        label: {
          formatter: "{b}: {c}",
          fontSize: 12,
          position: "start" as "start"
        },
        lineStyle: { width: 2, type: "dashed" as "dashed" }, // ← 阈值线更粗
        data: lines
      }
    : undefined;
}

/** 构造可选的 visualMap（越界染色） */
function buildVisualMap(): EChartsOption["visualMap"] {
  if (ucl.value == null && lcl.value == null) return undefined;
  return [
    {
      show: false,
      dimension: 1,
      pieces: [
        ...(lcl.value != null ? [{ lte: lcl.value, color: "#c23531" }] : []),
        {
          gt: lcl.value ?? -Infinity,
          lte: ucl.value ?? Infinity,
          color: "#2f4554"
        },
        ...(ucl.value != null ? [{ gt: ucl.value, color: "#d48265" }] : [])
      ]
    }
  ];
}

/** 抖动：把 [[site,value]] → [[index+偏移,value]] 并生成数值轴标签为 site */
function withJitter(raw: any[]) {
  const sites: string[] = Array.from(new Set(raw.map(d => d[0] as string)));
  const index = new Map(sites.map((s, i) => [s, i + 1]));
  const delta = 0.35; // 抖动强度：0.2~0.35 比较舒服

  const jittered = raw.map(([s, v]: [string, number]) => {
    const i = index.get(s) as number;
    return [i + (Math.random() * 2 - 1) * delta, v];
  });

  const xAxis: EChartsOption["xAxis"] = {
    type: "value",
    min: 0.5,
    max: sites.length + 0.5,
    name: "site",
    axisLabel: {
      formatter: (val: number) => {
        const i = Math.round(val) - 1;
        return sites[i] ?? "";
      },
      rotate: 45,
      margin: 12
    }
  };
  return { data: jittered, xAxis };
}

/** 构造完整 option（更粗的点、缩略图更高/更粗） */
function buildOption(raw: any[]): EChartsOption {
  const markLine = buildMarkLines();
  const visualMap = buildVisualMap();

  // 不抖动：直接用类目轴；抖动：换成数值轴并 jitter 数据
  let xAxis: EChartsOption["xAxis"];
  let seriesData: any[];

  if (props.jitter) {
    const j = withJitter(raw);
    xAxis = j.xAxis;
    seriesData = j.data;
  } else {
    const sites = Array.from(new Set(raw.map(d => d[0])));
    xAxis = {
      type: "category",
      name: "site",
      data: sites as string[],
      axisLabel: { rotate: 55, margin: 12 }
    };
    seriesData = raw;
  }

  const yZoomInside = { type: "inside", yAxisIndex: 0 };
  const yZoomSlider = { type: "slider", yAxisIndex: 0, right: 6, width: 12 };

  const option: EChartsOption = {
    title: {
      text: `当前测试项-` + props.testName,
      left: "center", // 标题居中
      top: 10,
      textStyle: {
        fontSize: 16,
        fontWeight: "bold"
      },
      subtextStyle: {
        fontSize: 12,
        color: "#888"
      }
    },
    animation: false,
    progressive: 4000,
    progressiveThreshold: 30000,
    toolbox: {
      right: 10,
      feature: { dataZoom: {}, restore: {}, saveAsImage: {} }
    },
    grid: { left: "8%", right: "5%", top: "10%" },
    dataZoom: [
      { type: "inside", xAxisIndex: 0 },
      {
        type: "slider",
        xAxisIndex: 0,
        height: 60,
        handleSize: "140%",
        dataBackground: { lineStyle: { width: 2 }, areaStyle: { opacity: 0.3 } }
      },
      yZoomInside,
      yZoomSlider
    ],
    xAxis,
    yAxis: {
      type: "value",
      name: "Value",
      nameGap: 12,
      splitLine: { show: true }
    },
    visualMap,
    series: [
      {
        name: "Probe Scatter",
        type: "scatter",
        data: seriesData,
        symbolSize: 7, // ← 点更大（粗）
        large: true,
        largeThreshold: 2000,
        itemStyle: {
          opacity: 0.9,
          borderWidth: 0.6,
          borderColor: "#2f4554"
        },
        markLine
      }
    ]
  };
  return option;
}

async function load() {
  initChart();
  if (!chart) {
    ElMessage.info("请先初始化图表");
    return;
  }
  if (!props.testName) {
    ElMessage.info("请先选择测试项");
    return;
  }
  chart.showLoading({ text: "Loading..." });
  try {
    const { data } = await axios.get<any[]>(props.apiUrl, {
      params: {
        testName: props.testName,
        dbPath: props.dbPath
      }
    });

    ucl.value = data.hLimit;
    lcl.value = data.lLimit;
    mean.value = data.mean;

    const option = buildOption(data.data ?? []);
    chart.setOption(option, true);
    loaded = true;
  } finally {
    chart.hideLoading();
  }
}

onMounted(async () => {
  await nextTick();
  initChart();
  await load();
  window.addEventListener("resize", resize);
});

// tab 被切到可见时，做一次 resize（首次可顺便加载）
watch(
  () => props.active,
  async now => {
    if (now) {
      await nextTick();
      await load();
      resize();
    }
  }
);

watch(
  () => props.testName,
  async (newTestName, oldTestName) => {
    if (newTestName) {
      await nextTick();
      // 无论是否已加载过，都重新加载数据
      await load();
      resize();
    }
  },
  { immediate: true } // 监听初次加载时的 testName
);

onBeforeUnmount(() => {
  window.removeEventListener("resize", resize);
  disposeChart();
});
</script>
